package cn.whitecao.contentcenter.config;

import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.alibaba.nacos.NacosDiscoveryProperties;
import org.springframework.cloud.alibaba.nacos.ribbon.NacosServer;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * nacos相同集群优先调用
 * @author ：腼腆的老黄.
 * @date ：Created in 2019-08-15 11:09
 */
@Slf4j
public class NacosSameClusterWeightedRule extends AbstractLoadBalancerRule {
    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object key) {
        try {
            //拿到配置文件中的集群名 Hangzhou
            String clusterName = nacosDiscoveryProperties.getClusterName();
            BaseLoadBalancer loadBalancer= (BaseLoadBalancer) this.getLoadBalancer();

            //拿到想要调用的服务名称
            String name = loadBalancer.getName();
            //拿到服务发现相关的API
            NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();

            //1.找到指定实例的所有服务
            List<Instance> instances = namingService.selectInstances(name, true);

            //2.过滤出相同集群下面的所有实例
            List<Instance> sameClusterInstance = instances.stream().filter(instance -> instance.getClusterName().equals(clusterName))
                    .collect(Collectors.toList());

            //3.如果为空就用其他的
            List<Instance> chosen = new ArrayList<>();
            if (CollectionUtils.isEmpty(sameClusterInstance)){
                chosen=instances;
                log.warn("发生跨集群调用 name:{} ,cluster-name:{},instance:{}",
                        name,clusterName,instances);
            }else{
                chosen=sameClusterInstance;
            }

            //4.基于权重选择
            Instance instance = ExtendBalancer.getByRandomWeight(chosen);
            log.info("nacos权重 选择的实例是: port={} , weight={} , instance={}",instance.getPort(),instance.getWeight(),instance);
            return new NacosServer(instance);
        } catch (NacosException e) {
           log.info("发生异常了: {}",e.getMessage());
            return null;
        }
    }

    public static class ExtendBalancer extends Balancer{
        public static Instance getByRandomWeight(List<Instance> hosts){
            return getHostByRandomWeight(hosts);
        }
    }
}














